package com.yjm.test.Spring5.ch3.methodReplacement;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.GenericXmlApplicationContext;
import org.springframework.util.StopWatch;

@Configuration
@ComponentScan(basePackages= {"com.yjm.test.Spring5.ch3.methodReplacement"})
public class MethodReplacement {

	public static void displayInfo(ReplacementTarget target) {
		System.out.println(target.formatMessage("Thanks for playing, try again!"));
		
		StopWatch stopWatch = new StopWatch();
		stopWatch.start("perfTest");
		for (int i = 0; i < 10000; i++) {
			String out = target.formatMessage("No filter in my head");
			//System.out.println(out);
		}
		stopWatch.stop();
		
		System.out.println("10000 invocations took:" + stopWatch.getLastTaskTimeMillis() + " ms");
	}
	
	public static void testXml() {
		GenericXmlApplicationContext ctx =  new GenericXmlApplicationContext();
		ctx.load("classpath:spring/ch3/method-replacer.xml");
		ctx.refresh();
		
		ReplacementTarget replacementTarget = ctx.getBean("replacementTarget", ReplacementTarget.class);
		ReplacementTarget standardTarget = ctx.getBean("standardTarget", ReplacementTarget.class);
		
		displayInfo(replacementTarget);
		displayInfo(standardTarget);
		ctx.close();
	}
	
	public static void testJavaConfig() {
		AnnotationConfigApplicationContext ctx =  new AnnotationConfigApplicationContext(MethodReplacement.class);
		
		ReplacementTarget replacementTarget = ctx.getBean("replacementTarget", ReplacementTarget.class);
		ReplacementTarget standardTarget = ctx.getBean("standardTarget", ReplacementTarget.class);
		
		displayInfo(replacementTarget);
		displayInfo(standardTarget);
		ctx.close();
	}
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		/*
		 *方法营换
虽然 Spring 丈档将方法替换归类为一种注入形式，但它与前面介绍的注入类型不同 。 到目前为止 ， 己经使用注
入向 bean 提供协作者。 通过使用方法替换，可以任意替换任何~ bean 的任何方法的实现，而无须更改所修改 bean 的
源代码。 例如 ， 有一个在 Spring 应用＊jll字中使用的第三方库 ， 并且需要更改某个方法的逻辑。 此时，无法更改源代
码，因为它是 由第三方提供的，所以一种解决方案是使用方法替换，使用自己的实现来替换该方法的逻辑。
在内部，可以通过动态创建 bean 类的子类来实现此目的 。 使用 CGLIB 并将想要替换的方法的调用重定向为另
一个实现了 MethodReplacer 接口的 bean ，在下面的代码示例中， 可以看到一个简单的 bean，它声明了 fonnatMessageO
方法的两个重载版本 ：



		 */
		testXml();
		System.out.println("\n\n");
		//testJavaConfig();

	}

}
